/***************************************************************************
 *            object_3d.c
 *
 *  Mon Aug 25 17:40:14 2008
 *  Copyright  2008  Tiago Falcão
 *  <tiago@tiagofalcao.com>
 ****************************************************************************/

/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Library General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301,  USA
 */
#include "object_3d.h"

// Cria Objeto 3D
object3d * obj3d_create(void (*display)(void *,unsigned int), void * object,void (*object_delete)(void *)){
	object3d * obj= calloc(1,sizeof(object3d));
	obj->display=display;							//Funcao de Display
	obj->object=object;								//Ponteiro de Estrutura do Objeto
	obj->object_delete=object_delete;				//Funcao de Delete do Objeto
	
	obj->color.r=1.;
	obj->color.g=1.;
	obj->color.b=1.;
	obj->color.a=1.;
	
	obj->matrix=matrix_create();					//Cria Matriz de Transformacao do Objeto
	
	return obj;										//Retorna Objeto
}

//Libera Objeto 3D
void obj3d_delete(object3d * obj){
	matrix_delete(obj->matrix);						//Libera Matriz
	obj->object_delete(obj->object);				//Deleta Estrutura de Dados do Objeto
	free(obj);										//Deleta Objeto
}

// Desenha Objeto 3D
void obj3d_display(object3d * obj){
	glPushMatrix ();
	//Transformação
	glMultMatrixf(obj->matrix);
	//Alfa
	if (obj->color.a<1.0){
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	}
	//Cor
	glColor4f(obj->color.r,obj->color.g,obj->color.b,obj->color.a);
	//Brilho
	glMaterialfv(GL_FRONT, GL_AMBIENT, obj->ambient);		//Ambiente
	glMaterialfv(GL_FRONT, GL_DIFFUSE, obj->diffuse);		//Difusao
	glMaterialfv(GL_FRONT, GL_SPECULAR, obj->specular);		//Reflexao
	glMaterialf(GL_FRONT, GL_SHININESS, obj->shininess);	//Concentracao
	glMaterialfv(GL_FRONT, GL_EMISSION, obj->emission);	 	//Emissao
	//Desenho do Objeto
	obj->display(obj->object,obj->mode);
	
	glPopMatrix ();
}

//Translacao em X
void obj3d_trans_x(object3d * obj,short int sign){
	GLfloat offset=sign*0.1;
	GLfloat * matrix=matrix_create();
	matrix[3]+=offset;
	matrix_mult_trans(obj->matrix,matrix);
	matrix_delete(matrix);
}
//Translacao em Y
void obj3d_trans_y(object3d * obj,short int sign){
	GLfloat offset=sign*0.1;
	GLfloat * matrix=matrix_create();
	matrix[7]+=offset;
	matrix_mult_trans(obj->matrix,matrix);
	matrix_delete(matrix);
}
//Translacao em Z
void obj3d_trans_z(object3d * obj,short int sign){
	GLfloat offset=sign*0.1;
	GLfloat * matrix=matrix_create();
	matrix[11]+=offset;
	matrix_mult_trans(obj->matrix,matrix);
	matrix_delete(matrix);
}

//Rotacao no eixo X
void obj3d_rot_x(object3d * obj,short int sign){
//	obj->rotate.x+=sign*10.0;
}
//Rotacao no eixo Y
void obj3d_rot_y(object3d * obj,short int sign){
//	obj->rotate.y+=sign*10.0;
}
//Rotacao no eixo Z
void obj3d_rot_z(object3d * obj,short int sign){
//	obj->rotate.z+=sign*10.0;
}

//Tamanho
void obj3d_size(object3d * obj,short int sign){
	GLfloat offset=sign*0.1;
	GLfloat * matrix=matrix_create();
	matrix[0]+=offset;
	matrix[5]+=offset;
	matrix[10]+=offset;
	matrix_mult_trans(obj->matrix,matrix);
	matrix_delete(matrix);
}

//Escala em X
void obj3d_scale_x(object3d * obj,short int sign){
	GLfloat offset=sign*0.1;
	GLfloat * matrix=matrix_create();
	matrix[0]+=offset;
	matrix_mult_trans(obj->matrix,matrix);
	matrix_delete(matrix);
}
//Escala em Y
void obj3d_scale_y(object3d * obj,short int sign){
	GLfloat offset=sign*0.1;
	GLfloat * matrix=matrix_create();
	matrix[5]+=offset;
	matrix_mult_trans(obj->matrix,matrix);
	matrix_delete(matrix);
}
//Escala em Z
void obj3d_scale_z(object3d * obj,short int sign){
	GLfloat offset=sign*0.1;
	GLfloat * matrix=matrix_create();
	matrix[10]+=offset;
	matrix_mult_trans(obj->matrix,matrix);
	matrix_delete(matrix);
}

//Seta Cor do Objeto
void obj3d_set_color(object3d * obj,GLfloat r, GLfloat g, GLfloat b, GLfloat a){
	obj->color.r=r;
	obj->color.g=g;
	obj->color.b=b;
	obj->color.a=a;
}

//Seta Ambiente
void obj3d_set_ambient(object3d * obj,GLfloat r, GLfloat g, GLfloat b, GLfloat a){
	obj->ambient[0]=r;
	obj->ambient[1]=g;
	obj->ambient[2]=b;
	obj->ambient[3]=a;
}

//Seta Difusa
void obj3d_set_diffuse(object3d * obj,GLfloat r, GLfloat g, GLfloat b, GLfloat a){
	obj->diffuse[0]=r;
	obj->diffuse[1]=g;
	obj->diffuse[2]=b;
	obj->diffuse[3]=a;
}

//Seta Especular
void obj3d_set_specular(object3d * obj,GLfloat r, GLfloat g, GLfloat b, GLfloat a){
	obj->specular[0]=r;
	obj->specular[1]=g;
	obj->specular[2]=b;
	obj->specular[3]=a;
}

//Seta Emissao
void obj3d_set_emission(object3d * obj,GLfloat r, GLfloat g, GLfloat b, GLfloat a){
	obj->emission[0]=r;
	obj->emission[1]=g;
	obj->emission[2]=b;
	obj->emission[3]=a;
}

//Seta Brilho
void obj3d_set_shininess(object3d * obj,GLfloat shininess){
	obj->shininess=shininess;
}
